﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright company="DHGMS Solutions" file="Csv.cs">
//   2004-2012 DHGMS Solutions. Some Rights Reserved. Licensed under GNU General Public License version 2 (GPLv2)
// </copyright>
// --------------------------------------------------------------------------------------------------------------------

namespace Dhgms.TplHelper.Controller.Task.SqlBulkCopy
{
    using System;
    using System.Data;
    using System.Linq;

    using Dhgms.DataManager.Model.Exception;
    using Dhgms.DataManager.Model.Helper;
    using Dhgms.DataManager.Model.Info;
    using Dhgms.TplHelper.Model.Info;

    using Kent.Boogaart.KBCsv;
    using Kent.Boogaart.KBCsv.Extensions;

    /// <summary>
    /// Bulk Inserts a CSV file into MS SQL Server
    /// </summary>
    /// <typeparam name="TInformationClass">
    /// The information class that represents the file being imported
    /// </typeparam>
    public class Csv<TInformationClass> : File
        where TInformationClass : Base<TInformationClass>, new()
    {
        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="Csv{TInformationClass}"/> class. 
        /// </summary>
        /// <param name="taskName">
        /// Name of the data being bulk imported
        /// </param>
        /// <param name="sourceFileName">
        /// Location of the CSV file to import
        /// </param>
        /// <param name="destinationConnectionString">
        /// Connection String for the target database
        /// </param>
        /// <param name="destinationDatabase">
        /// Name of the database the table sits in
        /// </param>
        /// <param name="destinationSchema">
        /// the schema the destination table sits in
        /// </param>
        /// <param name="destinationTable">
        /// the table the data is going to end up in
        /// </param>
        /// <param name="targetTableDeleteAction">
        /// the delete action to be taken on the target table
        /// </param>
        public Csv(
            string taskName, 
            string sourceFileName, 
            string destinationConnectionString,
            string destinationDatabase,
            string destinationSchema, 
            string destinationTable, 
            DestinationTableDeleteAction targetTableDeleteAction)
            : base(taskName, destinationConnectionString, destinationDatabase, destinationSchema, destinationTable, targetTableDeleteAction)
        {
            if (string.IsNullOrWhiteSpace(sourceFileName))
            {
                throw new ArgumentNullException("sourceFileName");
            }

            this.SourceFileName = sourceFileName;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the name of the file we pull the data from
        /// </summary>
        private string SourceFileName { get; set; }

        #endregion

        #region Methods

        /// <summary>
        /// Fetches the data and passes it on to be bulk inserted
        /// </summary>
        protected override void OnFetchAndProcessSourceData()
        {
            using (var input = new CsvReader(this.SourceFileName))
            {
                this.OnOverrideFileFormat(input);

                // get the file header record
                input.ReadHeaderRecord();
                string[] fileHeaderRecord = input.HeaderRecord.ToArray();

                // check against the expected header record
                var infoClass = new TInformationClass();
                string[] expectedHeader = infoClass.HeaderRecord.ToArray();
                if (expectedHeader.CompareCollection(fileHeaderRecord, StringComparison.OrdinalIgnoreCase) != 0)
                {
                    throw new UnexpectedFileFormatException();
                }

                // load the data
                var dataSet = new DataSet();
                dataSet.Fill(input);

                var dataReader = dataSet.CreateDataReader();
                this.ActOnData(dataReader);
            }
        }

        /// <summary>
        /// Used to change the output format, if needed
        /// </summary>
        /// <param name="output">
        /// output object
        /// </param>
        protected virtual void OnOverrideFileFormat(CsvReader output)
        {
        }

        #endregion
    }
}